/*
 * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of Intel Corporation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef _UTIL_ST_H_
#define _UTIL_ST_H_

#include "se_cdefs.h"
#include "se_memcpy.h"
#include <stdio.h>


#define USAGE_STRING \
    "\nUsage: sgx_sign <commands> [options] file...\n"\
    "Commands:\n"\
    "   sign                    Sign the enclave using the private key\n"\
    "   gendata                 Generate enclave signing material to be signed\n"\
    "   catsig                  Generate the signed enclave with the input signature file, the\n"\
    "                           public key and the enclave signing material\n"\
    "   dump                    Dump metadata information for a signed enclave file\n"\
    "Options:\n"\
    "   -enclave                Specify the enclave file to be signed or already signed\n"\
    "                           It is a required option for the four commands\n"\
    "   -key                    Specify the key file\n"\
    "                           It is a required option for \"sign\" and \"catsig\"\n"\
    "   -config                 Specify the configuration for the enclave\n"\
    "   -out                    Specify the output file\n"\
    "                           It is a required option for \"sign\", \"gendata\" and \"catsig\"\n"\
    "   -sig                    Specify the signature file for the enclave signing material\n" \
    "                           It is a required option for \"catsig\"\n"\
    "   -unsigned               Specify the enclave signing material generated by \"gendata\"\n" \
    "                           It is a required option for \"catsig\"\n" \
    "   -dumpfile               Specify a file to dump metadata information (text format)\n" \
    "                           It is a required option for \"dump\"\n" \
    "   -cssfile                Specify a file to dump the enclave SIGSTRUCT information (binary format)\n" \
    "   -ignore-rel-error       By default, sgx_sign provides an error for enclaves with\n" \
    "                           text relocations. You can ignore the error and continue signing\n" \
    "                           by providing this option. But it is recommended you eliminate the\n" \
    "                           text relocations instead of bypassing the error with this option.\n" \
    "   -ignore-init-sec-error  By default, sgx_sign provides an error for enclaves with .init section.\n" \
    "                           You can ignore the error and continue signing by providing this option.\n" \
    "                           But it is recommended you eliminate the section instead of bypassing\n" \
    "                           the error with this option.\n" \
    "   -resign                 By default, sgx_sign reports an error if an input enclave has already been signed.\n" \
    "                           You can force sgx_sign to resign the enclave by providing this option.\n\n" \
    "Run \"sgx_sign -help\" to get this help and exit.\n" \
    "Run \"sgx_sign -version\" to output version information and exit.\n\n"


#define VERSION_STRING \
    "\nThis is sgx_sign from Intel(R) Software Guard Extensions, version %s for Linux.\n\n%s\n\n" \
    "BSD License. The License file could be found under the Intel(R) SGX SDK package.\n\n"

// General error message
#define OVERALL_ERROR                       "Error happened while signing the enclave.\n"
#define KEY_FORMAT_ERROR                    "Key file format is not correct.\n"
#define XML_FORMAT_ERROR                    "Configuration file format is not correct.\n"
#define XML_NOT_FOUND_ERROR                 "Configuration file \"%s\" is not found.\n"
#define NO_MEMORY_ERROR                     "Out of memory.\n"
#define OPEN_FILE_ERROR                     "Failed to open file \"%s\".\n"
#define READ_FILE_ERROR                     "Failed to read file \"%s\".\n"
#define WRITE_FILE_ERROR                    "Failed to write file \"%s\".\n"

// error message for measure_enclave()
#define OUT_OF_EPC_ERROR                    "The required memory is too large. Please check TCSNum/HeapMaxSize/StackMaxSize.\n"
#define META_VERSION_ERROR                  "Metadata version is mismatched between uRTS and sgx_sign.\n"
#define INVALID_ENCLAVE_ERROR               "The input enclave file is not correct.\n"
#define REQUIRED_ENCLAVE_SIZE               "The required memory is %lluB.\n"
#define TEXT_REL_ERROR                      "The enclave image has text relocations.\n"
#define INIT_SEC_ERROR                      "The enclave image has .init section.\n"

// error message for fill_enclave_css()
#define UNSIGNED_FILE_ERROR                 "The unsigned file \"%s\" is not correct.\n"
#define UNSIGNED_FILE_XML_MISMATCH          "The unsigned file content doesn't match the configuration file (if provided) or the internal configuration defaults.\n"

// error message for create_signature()
#define SIG_FILE_ERROR                      "The signature file \"%s\" is not correct.\n"

// error message for cmdline_parse()
#define LACK_PARA_ERROR                     "Lack of parameters.\n"
#define UNREC_CMD_ERROR                     "Cannot recognize the command \"%s\".\nCommand \"sign/gendata/catsig\" is required.\n"
#define REPEAT_OPTION_ERROR                 "Repeatly specified \"%s\" option.\n"
#define INVALID_FILE_NAME_ERROR             "The File name is not correct for \"%s\" option.\n"
#define LACK_REQUIRED_OPTION_ERROR          "Option \"%s\" is required for the command \"%s\".\n"
#define GIVE_INVALID_OPTION_ERROR           "Option \"%s\" is invalid for the command \"%s\".\n"
#define UNREC_OPTION_ERROR                  "Cannot recognize the option \"%s\".\n"
#define DUPLICATED_FILE_NAME_ERROR          "Option \"%s\" and option \"%s\" are using the same file path.\n"

// error message for generate_output()
#define LACK_PRI_KEY_ERROR                  "Private key is required for the \"sign\" command.\n"
#define LACK_PUB_KEY_ERROR                  "Public key is required for the \"catsig\" command.\n"

// error message for main()
#define ENCLAVE_ALREADY_SIGNED_ERROR        "The enclave has been signed already.\n"
#define DUMP_METADATA_ERROR                 "Failed to dump metadata info to file \"%s\".\n."
#define SUCCESS_EXIT                        "Succeed.\n"

// error message for traverser_parameter()
#define LACK_VALUE_FOR_ELEMENT_ERROR        "No value for the element \"%s\".\n"
#define INVALID_VALUE_FOR_ELEMENT_ERROR     "Invalid value for the element\"%s\".\n"
#define UNREC_ELEMENT_ERROR                 "Element is not recognized - \"%s\".\n"
#define REPEATED_DEFINE_ERROR               "Defined \"%s\" too many times.\n"
#define VALUE_OUT_OF_RANGE_ERROR            "The value of \"%s\" is out of range.\n"

// error message for modify_metadata()
#define SET_STACK_SIZE_ERROR                "Stack size setting is not correct.\n"
#define SET_HEAP_SIZE_ALIGN_ERROR           "Heap size setting is not correct: size is not page aligned.\n"
#define SET_HEAP_SIZE_INIT_MAX_ERROR        "Heap size setting is not correct: init value should not be larger than max value.\n"
#define SET_HEAP_SIZE_INIT_MIN_ERROR        "Heap size setting is not correct: min value should not be larger than init value.\n"
#define SET_HEAP_SIZE_MAX_MIN_ERROR         "Heap size setting is not correct: max value should not be smaller than min value.\n"
#define SET_RSRV_SIZE_ALIGN_ERROR           "Reserved memory size setting is not correct: size is not page aligned.\n"
#define SET_RSRV_SIZE_INIT_MAX_ERROR        "Reserved memory size setting is not correct: init value should not be larger than max value.\n"
#define SET_RSRV_SIZE_INIT_MIN_ERROR        "Reserved memory size setting is not correct: min value should not be larger than init value.\n"
#define SET_RSRV_SIZE_MAX_MIN_ERROR         "Reserved memory size setting is not correct: max value should not be smaller than min value.\n"
#define SET_RSRV_EXECUTABLE_ERROR           "Reserved memory executable setting is not correct: the executable value should be set to 1 or 0.\n"
#define SET_USER_REGION_SIZE_ALIGN_ERROR    "User region size setting is not correct: size is not page aligned.\n"
#define SET_HW_LE_ERROR                     "Conflicting setting between the 'HW' and 'LaunchKey'.\n"
#define SET_TCS_MAX_NUM_ERROR               "Maximum number of TCS is not correct.\n"
#define SET_TCS_MIN_POOL_ERROR              "Minimum number of TCS Pool is not correct.\n"
#define SET_ENABLE_KSS_ERROR                "KSS must be enabled if ISVEXTPRODID or ISVFAMILYID is set.\n"

#define SET_ENCLAVEIMAGEADDRESS_SET_ERROR           "ELRangeSize must be set when EnclaveImageAddress is set.\n"
#define SET_ENCLAVEIMAGEADDRESS_ERROR               "EnclaveImageAddress setting is not correct. EnclaveImageAddress plus EnclaveSize should not overflow.\n"
#define SET_ENCLAVEIMAGEADDRESS_ALIGN_ERROR         "EnclaveImageAddress setting is not correct: EnclaveImageAddress is not page aligned.\n"
#define SET_ELRANGESTARTADDRESS_SET_ERROR           "ELRangeSize must be set when ELRangeStartAddress is set.\n\n"
#define SET_ELRANGESTARTADDRESS_PAGE_ALIGN_ERROR    "ELRangeStartAddress setting is not correct: ELRangeStartAddress is not page aligned.\n"
#define SET_ELRANGESTARTADDRESS_ALIGN_ERROR         "ELRangeStartAddress and ELRangeSize setting are not correct: ELRangeStartAddress should be aligned on an ELRangeSize boundary.\n"
#define SET_ELRANGESTARTADDRESS_RANGE_ERROR         "ELRangeStartAddress setting is not correct: ELRangeStartAddress should not bigger than EnclaveImageAddress.\n"
#define SET_ELRANGE_ERROR                           "ELRange setting is not correct. ELRangeStartAddress plus ELRangeSize should not overflow.\n"
#define SET_ELRANGE_RANGE_ERROR                     "ELRange setting is not correct: ELRange should be large enough to fit the enclave image loaded at EnclaveImageAddress.\n"
#define SET_ELRANGE_ALIGN_ERROR                     "ELRangeSize setting is not correct: ELRangeSize should be power of 2.\n"
#define SET_ELRANGE_PAGE_ALIGN_ERROR                "ELRangeSize setting is not correct: ELRangeSize is not page aligned.\n"





#define SDK_VERSION_ERROR                   "SDK version is not correct. The same SDK should be used for enclave building and signing.\n"\
                                            "The SDK version for building enclave could be obtained by below command:\n\n"\
                                            "           $ strings {Enclave.so} | grep SGX_TSTDC_VERSION \n\n"


// error message for parse_key_file()
#define INVALID_EXPONENT_ERROR              "The exponent of the input key is invalid. Only '3' is accepted as the exponent.\n"
#define INVALID_KEYSIZE_ERROR               "The required key size must be 3072 bits.\n"


#include <stdint.h>
#include <iostream>


typedef enum _command_mode_t
{
    SIGN = 0,
    GENDATA,
    CATSIG,
    DUMP
} command_mode_t;


#ifdef __cplusplus
extern "C" {
#endif

size_t get_file_size(const char *filename);
bool read_file_to_buf(const char *filename, uint8_t *buffer, size_t bsize);
bool write_data_to_file(const char *filename, std::ios_base::openmode mode, uint8_t *buf, size_t bsize, long offset = 0);
bool copy_file(const char *source_path, const char *dest_path);

#ifdef __cplusplus
}
#endif

#endif
